import unittest
from os import getcwd as pwd
import os.path
import cgi

import cotton.tal as tal
import random

# Tests
class test_tal(unittest.TestCase):
    def setUp(self):
        self.base = get_base_path()

class test_tal_define(test_tal):
    def test_var_simple(self):
        template = wrap("""<p tal:define='test2 as var:test' tal:content='var:test2'>FAILED</p>""")
        page = tal.page(template, self.base)
        page.add( {'test' : 'SUCCESS'} )
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_var_nested(self):
        template = wrap("""<p tal:define='test as var:test[nest]' tal:content='var:test'>FAILED</p>""")
        page = tal.page(template, self.base)
        page.add( {'test' : {'nest' : 'SUCCESS'}} )
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_var_nested_var(self):
        template = wrap("""<p tal:define='test as var:test[`nest]' tal:content='var:test'>FAILED</p>""")
        page = tal.page(template, self.base)
        page.add( {'test' : {'foo' : 'SUCCESS'}, 'nest' : 'foo'} )
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_var_nested_index(self):
        template = wrap("""<p tal:define='test as var:test[0]' tal:content='var:test'>FAILED</p>""")
        page = tal.page(template, self.base)
        page.add( {'test' : ['SUCCESS', 'FAILED']} )
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_fail_on_int(self):
        template = wrap("""<p tal:define='test as var:1' tal:content='var:test'>SUCCESS</p>""")
        page = tal.page(template, self.base)
        page.add( {1 : 'FAILED'} )
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_fail_on_int_2(self):
        template = wrap("""<p tal:define='test as var:1' tal:content='var:test'>SUCCESS</p>""")
        page = tal.page(template, self.base)
        page.add( {'1' : 'FAILED'} )
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_fail_on_bad_var_name(self):
        template = wrap("""<p tal:define='test as var:1test' tal:content='var:test'>SUCCESS</p>""")
        page = tal.page(template, self.base)
        page.add( {'1test' : 'FAILED'} )
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_fail_on_bad_characters(self):
        for char in "&<>`-=~!@#$%^*()+[]\{}|;':\",./?\t\n":
            template = wrap("""<p tal:define='test as var:""" + str(char) + """' tal:content='var:test'>SUCCESS</p>""" )
            page = tal.page(template, self.base)
            page.add( {str(char) : 'FAILED: ' + str(char)} )
            self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_fail_on_no_var(self):
        template = wrap("""<p tal:define='test as var:' tal:content='var:test'>SUCCESS</p>""")
        page = tal.page(template, self.base)
        page.add( {'' : 'FAILED'} )
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_fail_on_no_var_2(self):
        template = wrap("""<p tal:define='test as var:' tal:content='var:test'>SUCCESS</p>""")
        page = tal.page(template, self.base)
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_fail_on_no_prefix(self):
        template = wrap("""<p tal:define='test2 as test' tal:content='var:test2'>SUCCESS</p>""")
        page = tal.page(template, self.base)
        page.add( {'test' : 'FAILED'} )
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_fun(self):
        template = wrap("""<p tal:define='test as fun:cotton.test.get_string()' tal:content='var:test'>FAILED</p>""")
        page = tal.page(template, self.base)
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_fun_with_arguments(self):
        template = wrap("""<p tal:define='test as fun:cotton.test.get_concat(a,b)' tal:content='var:test'>FAILED</p>""")
        page = tal.page(template, self.base)
        page.add( {'a' : 'SUCC', 'b' : 'ESS'} )
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_fail_with_wrong_args(self):
        template = wrap("""<p tal:define='test as fun:cotton.test.get_concat(a)' tal:content='var:test'>SUCCESS</p>""")
        page = tal.page(template, self.base)
        page.add( {'a' : 'FAILED', 'b' : 'ESS'} )
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_fail_on_no_fun(self):
        template = wrap("""<p tal:define='test as fun:' tal:content='var:test'>SUCCESS</p>""")
        page = tal.page(template, self.base)
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_fail_on_no_prefix(self):
        template = wrap("""<p tal:define='test2 as cotton.test.string()' tal:content='var:test2'>REAL SUCCESS</p>""")
        page = tal.page(template, self.base)
        self.assertEqual(page.expand(), wrap("""<p>REAL SUCCESS</p>"""))

    def test_fail_on_multiple_tal_statements(self):
        template = wrap("""<p tal:define='test as fun:cotton.test.get_string()' tal:define='test2 as fun:cotton.test.get_fail_string()' tal:content='var:test'>FAILED</p>""")
        page = tal.page(template, self.base)
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

class test_tal_if(test_tal):
    def test_simple(self):
        template = wrap("""<p tal:if='var:test'>SUCCESS</p><p tal:if='not:var:test'>FAILED</p>""")
        page = tal.page(template, self.base)
        page.add( {'test' : True} )
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

    def test_fail_on_improper_order(self):
        template = wrap("""<p tal:if='var:not:test'>SUCCESS</p>""")
        page = tal.page(template, self.base)
        page.add( {'test' : True} )
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

class test_tal_import(test_tal):
    def test_simple(self):
        template = wrap("""<div tal:import='export_1 from tal_import_test_1.html'>FAILED</div>""")
        page = tal.page(template, self.base)
        self.assertEqual(page.expand(), wrap("""<div><p>SLOT WAS NOT FILLED</p><p>SUCCESS</p></div>"""))

    def test_fill_slot(self):
        template = wrap("""<div tal:import='export_1 from tal_import_test_1.html'>FAILED<p tal:fill='slot_1'>SUCCESS</p></div>""")
        page = tal.page(template, self.base)
        self.assertEqual(page.expand(), wrap("""<div><p>SUCCESS</p><p>SUCCESS</p></div>"""))

    def test_nested_import(self):
        template = wrap("""<div tal:import='export_2 from tal_import_test_2.html'>FAILED</div>""")
        page = tal.page(template, self.base)
        self.assertEqual(page.expand(), wrap("""<div><div><p>SUCCESS</p><p>SUCCESS</p></div></div>"""))

class test_tal_content(test_tal):
    def test_simple(self):
        template = wrap("""<p tal:content='var:test'>FAILED</p>""")
        page = tal.page(template, self.base)
        page.add( {'test' : 'SUCCESS'} )
        self.assertEqual(page.expand(), wrap("""<p>SUCCESS</p>"""))

class test_tal_for(test_tal):
    def test_simple(self):
        template = wrap("""<div tal:for='item in var:list'><p tal:content='var:item'>FAIL</p></div>""")
        page = tal.page(template, self.base)
        page.add( {'list' : ['SUCCESS', 'ANOTHER SUCCESS']} )
        self.assertEqual(page.expand(), wrap("""<div><p>SUCCESS</p><p>ANOTHER SUCCESS</p></div>"""))

    def test_tricky_tail(self):
        template = wrap("""<div tal:for='item in var:list'><p tal:content='var:item'>FAIL</p>tail text</div>""")
        page = tal.page(template, self.base)
        page.add( {'list' : ['SUCCESS', 'ANOTHER SUCCESS']} )
        self.assertEqual(page.expand(), wrap("""<div><p>SUCCESS</p>tail text<p>ANOTHER SUCCESS</p>tail text</div>"""))

    def test_tricky_main_text(self):
        template = wrap("""<div tal:for='item in var:list'>main text<p tal:content='var:item'>FAIL</p></div>""")
        page = tal.page(template, self.base)
        page.add( {'list' : ['SUCCESS', 'ANOTHER SUCCESS']} )
        self.assertEqual(page.expand(), wrap("""<div>main text<p>SUCCESS</p>main text<p>ANOTHER SUCCESS</p></div>"""))

class test_tal_set(test_tal):
    def test_simple(self):
        template = wrap("""<p id='FAIL' tal:set='id to var:test'>SUCCESS</p>""")
        page = tal.page(template, self.base)
        page.add( {'test' : 'SUCCESS'} )
        self.assertEqual(page.expand(), wrap("""<p id="SUCCESS">SUCCESS</p>"""))

# Support functions
def get_base_path():
    return pwd()

def wrap(string):
    header = """<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">\n<html><body>"""
    footer = """</body></html>"""
    return header + str(string) + footer

def get_string():
    return "SUCCESS"

def get_fail_string():
    return "FAIL STRING"

def get_concat(a,b):
    return str(a) + str(b)


if(__name__ == "__main__"):
    unittest.main()
